package cn.ming.leo.resource;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.api.PaymentApi.TradeType;
import com.jfinal.weixin.sdk.kit.PaymentKit;

import cn.ming.leo.bean.OrderInfo;
import cn.ming.leo.bean.User;
import cn.ming.leo.service.DoorToolsService;
import cn.ming.leo.utils.TimeFormat;

@RestController
@RequestMapping("/pay")
public class WechatPayResource {
	static Log log = Log.getLog(WechatPayResource.class);
	private final static String PATERNERKEY = "paternerKey";
	private final static String NOTIFY_URL = "https://api.aituolink.xyz/leo/pay/payNotify";

	@Autowired
	DoorToolsService doorToolsService;

	@RequestMapping(value = "/prepare")
	public void prepare(HttpServletRequest request, HttpServletResponse response) {
		try {
			/**
			 * 获取用户扫描二维码后，微信返回的信息
			 */
			InputStream inStream = request.getInputStream();
			ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			outSteam.close();
			inStream.close();
			String result = new String(outSteam.toByteArray(), "utf-8");
			System.out.println("callBack_xml>>>" + result);
			/**
			 * 获取返回的信息内容中各个参数的值
			 */
			Map<String, String> map = PaymentKit.xmlToMap(result);
			for (String key : map.keySet()) {
				System.out.println("key= " + key + " and value= " + map.get(key));
			}

			String appid = map.get("appid");
			String openid = map.get("openid");

			User user = User.find.where().eq("open_id", openid).findUnique();
			if (user == null) {
				response.getWriter().write("请先注册");
			}
			String mch_id = map.get("mch_id");
			String is_subscribe = map.get("is_subscribe");
			String nonce_str = map.get("nonce_str");
			String product_id = map.get("product_id");
			String sign = map.get("sign");
			Map<String, String> packageParams = new HashMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("openid", openid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("is_subscribe", is_subscribe);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("product_id", product_id);

			String packageSign = PaymentKit.createSign(packageParams, PATERNERKEY);
			// 统一下单文档地址：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

			Map<String, String> params = new HashMap<String, String>();
			params.put("appid", appid);
			params.put("mch_id", mch_id);
			params.put("body", "扫码支付");
			String out_trade_no = Long.toString(System.currentTimeMillis());
			params.put("out_trade_no", out_trade_no);
			int price = 1;
			if ("1".equals(product_id)) {
				price = ((int) (Float.valueOf(10) * 100));
			} else if ("2".equals(product_id)) {
				price = ((int) (Float.valueOf(50) * 100));
			} else if ("3".equals(product_id)) {
				price = ((int) (Float.valueOf(100) * 100));
			}

			params.put("total_fee", price + "");
			params.put("attach", out_trade_no);

			String ip = "127.0.0.1";

			params.put("spbill_create_ip", ip);
			params.put("trade_type", TradeType.NATIVE.name());
			params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
			params.put("notify_url", NOTIFY_URL);
			params.put("openid", openid);

			String paysign = PaymentKit.createSign(params, PATERNERKEY);
			params.put("sign", paysign);

			String xmlResult = PaymentApi.pushOrder(params);

			System.out.println("prepay_xml>>>" + xmlResult);

			/**
			 * 发送信息给微信服务器
			 */
			Map<String, String> payResult = PaymentKit.xmlToMap(xmlResult);

			String return_code = payResult.get("return_code");
			String result_code = payResult.get("result_code");

			if (StrKit.notBlank(return_code) && StrKit.notBlank(result_code) && return_code.equalsIgnoreCase("SUCCESS")
					&& result_code.equalsIgnoreCase("SUCCESS")) {
				// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
				String prepay_id = payResult.get("prepay_id");

				Map<String, String> prepayParams = new HashMap<String, String>();
				prepayParams.put("return_code", "SUCCESS");
				prepayParams.put("appId", appid);
				prepayParams.put("mch_id", mch_id);
				prepayParams.put("nonceStr", System.currentTimeMillis() + "");
				prepayParams.put("prepay_id", prepay_id);
				String prepaySign = null;
				if (sign.equals(packageSign)) {
					prepayParams.put("result_code", "SUCCESS");
				} else {
					prepayParams.put("result_code", "FAIL");
					prepayParams.put("err_code_des", "订单失效"); // result_code为FAIL时，添加该键值对，value值是微信告诉客户的信息
				}
				prepaySign = PaymentKit.createSign(prepayParams, PATERNERKEY);
				prepayParams.put("sign", prepaySign);
				String xml = PaymentKit.toXml(prepayParams);
				log.error(xml);
				response.getWriter().write(xml);

			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@SuppressWarnings("unchecked")
	public static Map<String, String> parseXml(String msg) throws Exception {
		// 将解析结果存储在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		// 从request中取得输入流
		InputStream inputStream = new ByteArrayInputStream(msg.getBytes("UTF-8"));

		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		List<Element> elementList = root.elements();

		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		// 释放资源
		inputStream.close();
		inputStream = null;

		return map;
	}

	@RequestMapping(value = "/payNotify")
	public void pay_notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream()));
		StringBuilder sb = new StringBuilder("");
		String line = null;
		while ((line = in.readLine()) != null) {
			sb.append(line.trim());
		}

		Map<String, String> params = parseXml(sb.toString());
		String result_code = params.get("result_code");
		String openId = params.get("openid");
		// 交易类型
		String trade_type = params.get("trade_type");
		// 付款银行
		String bank_type = params.get("bank_type");
		// 总金额
		String total_fee = params.get("total_fee");
		// 微信支付订单号
		String transaction_id = params.get("transaction_id");
		// 商户订单号
		String out_trade_no = params.get("out_trade_no");
		// 支付完成时间，格式为yyyyMMddHHmmss
		String time_end = params.get("time_end");

		///////////////////////////// 以下是附加参数///////////////////////////////////

		String attach = params.get("attach");
		// String fee_type = params.get("fee_type");
		// String is_subscribe = params.get("is_subscribe");
		// String err_code = params.get("err_code");
		// String err_code_des = params.get("err_code_des");

		// 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
		// 避免已经成功、关闭、退款的订单被再次更新
		OrderInfo order = OrderInfo.find.where().eq("order_no", transaction_id).findUnique();

		if (order == null) {
			if (PaymentKit.verifyNotify(params, PATERNERKEY)) {
				if (("SUCCESS").equals(result_code)) {
					order = new OrderInfo();
					order.setCreateTime(TimeFormat.nowTime());
					order.setUpdateTime(new Date());
					order.setOrderNo(transaction_id);
					order.setOpenId(openId);

					User user = User.find.where().eq("open_id", openId).findUnique();

					order.setUserId(user.getId());
					order.setOutTradeNo(out_trade_no);
					order.setTradeType(trade_type);
					order.setBankType(bank_type);
					order.setTotalFee(total_fee);
					order.setTimeEnd(time_end);

					order.save();
					BigDecimal totalFee = new BigDecimal(total_fee).divide(new BigDecimal(100));
					user.setAmount(user.getAmount().add(totalFee));
					user.update();

					// 更新订单信息
					log.warn("更新订单信息:" + attach);
					// 发送通知等
					Map<String, String> xml = new HashMap<String, String>();
					xml.put("return_code", "SUCCESS");
					xml.put("return_msg", "OK");
					response.getWriter().write(PaymentKit.toXml(xml));
					return;
				}
			}
		}
		response.getWriter().write("");
	}

}
